package com.zhaoyuxi.redpack.service.impl;

import com.zhaoyuxi.redpack.entity.TbRedpack;
import com.zhaoyuxi.redpack.entity.TbUserRedpack;
import com.zhaoyuxi.redpack.mapper.TbUserRedpackMapper;
import com.zhaoyuxi.redpack.service.ITbRedpackService;
import com.zhaoyuxi.redpack.service.ITbUserRedpackService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.zhaoyuxi.redpack.service.RedisService;
import com.zhaoyuxi.util.RedPacketUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 赵玉玺
 * @since 2020-04-02
 */
@Service
@Slf4j
public class TbUserRedpackServiceImpl extends ServiceImpl<TbUserRedpackMapper, TbUserRedpack> implements ITbUserRedpackService {

    @Autowired
    private ITbRedpackService iTbRedpackService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public String getPack() {
        try {
            TbRedpack tbRedpack = iTbRedpackService.getOne(1);
            if (tbRedpack.getRemain().doubleValue() > 0) {
                tbRedpack.setRemain(tbRedpack.getRemain().subtract(BigDecimal.ONE));
                boolean updateById = iTbRedpackService.updateById(tbRedpack);
                if (updateById) {
                    //3.新增用户抢红包记录
                    TbUserRedpack userRedpack = new TbUserRedpack();
                    userRedpack.setUserId(tbRedpack.getUserId());
                    userRedpack.setRedpackId(tbRedpack.getId());
                    userRedpack.setGrabDate(new Date());
                    userRedpack.setAmount(new BigDecimal(String.valueOf(tbRedpack.getAmount())));
                    this.baseMapper.insert(userRedpack);
                    return "抢红包成功";
                }

            }
            //异步通知用户抢红包成功
        } catch (Exception e) {
            log.error("处理抢单异常：" + e.getMessage());
            throw new RuntimeException("处理抢单异常");
        } finally {
            return "抢红包成功";
        }
    }

    @Override
    public String getPackRedis() {
        try {
            while (true) {
                TbRedpack tbRedpack = redisService.selectRemain();
                if (tbRedpack.getRemain().doubleValue() > 0) {
                    boolean update = redisService.update(tbRedpack.getVersion());
                    if (update) {
                        //3.新增用户抢红包记录
                        redisService.addRedPackDetail(BigDecimal.ONE);
                        return "抢红包成功";
                    }
                }
            }
            //异步通知用户抢红包成功
        } catch (Exception e) {
            log.error("处理抢单异常：" + e.getMessage());
            throw new RuntimeException("处理抢单异常");
        } finally {
            return "抢红包成功";
        }
    }

    /**
     * redis 乐观锁 事务的方式处理
     * @return
     */
    @Override
    public String getPackRedis2() {
        try {
            ValueOperations valueOperations = redisTemplate.opsForValue();
            //开启事务
            redisTemplate.setEnableTransactionSupport(true);
            while (true) {

                //监视器（get必须在其后）
                redisTemplate.watch("redpack");
                TbRedpack tbRedpack = (TbRedpack) valueOperations.get("redpack");
                if (tbRedpack.getRemain().doubleValue()> 0 && tbRedpack.getTotal()>0) {

                    BigDecimal one = BigDecimal.valueOf(RedPacketUtil.randomRedPacket(tbRedpack.getRemain().floatValue(), RedPacketUtil.RedPacket.MINMONEY.getValue(), RedPacketUtil.RedPacket.MAXMONEY.getValue(), tbRedpack.getTotal()));
                    tbRedpack.setRemain(tbRedpack.getRemain().subtract(one));
                    tbRedpack.setTotal(tbRedpack.getTotal()-1);
                    //乐观锁的配置
                    tbRedpack.setVersion(tbRedpack.getVersion() + 1);
                    //事务开始
                    redisTemplate.multi();
                    valueOperations.set("redpack", tbRedpack);
                    //事务结束返回结果
                    List exec = redisTemplate.exec();
                    if (exec.size() > 0) {
                        //操作成功
                        redisService.addRedPackDetail(one);
                        System.out.println( "抢红包成功！");
                    } else {
                        System.out.println("抢红包失败！");
                    }
                }else {
                    System.out.println("红包没有了，都抢光了....");
                    return "红包没有了，都抢光了....";
                }
            }
            //异步通知用户抢红包成功
        } catch (Exception e) {
            log.error("处理抢单异常：" ,e);
            throw new RuntimeException("处理抢单异常");
        } finally {
            return "抢红包成功";
        }
    }
}
